23. 物流行业数据分析

课程目标

通过本案例,你将学会:

  • 使用 Pandas 对物流数据进行清洗与转换
  • 从多个维度分析配送时效性问题
  • 识别具有销售潜力的区域与货品
  • 基于用户反馈评估产品质量问题
  • 综合分析结果提出业务改进建议

物流数据分析的核心维度

物流行业的数据分析通常围绕四个关键维度展开:

维度 核心指标 分析目标
时效性 按时交货率 配送服务是否达标
质量 合格率、返修率 产品是否存在缺陷
区域 各区域表现对比 识别薄弱区域
货品 各货品销售与反馈 识别问题货品

数据清洗流程概述

本案例的数据清洗包含以下关键步骤:

  • 删除重复记录drop_duplicates() 保留首次出现的记录
  • 删除缺失值dropna() 删除含缺失值的行
  • 删除无关列drop(columns=['订单行']) 移除无用字段
  • 重置索引reset_index(drop=True) 更新行索引
  • 金额转换:将 ‘万元’ 和 ‘元’ 统一为数值格式
  • 删除异常值:移除销售金额为 0 的记录

⭐ 平台任务:物流数据分析完整代码

Listing 1
# 注:data_wuliu.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import os  # 导入操作系统接口模块
import pandas as pd  # 导入Pandas数据分析库
import numpy as np  # 导入NumPy数值计算库
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
plt.rcParams['font.sans-serif'] = 'SimHei' ## 设置中文显示

## 数据清洗部分
data = pd.read_csv('data_wuliu.csv',encoding='gbk')

#删除重复记录
data.drop_duplicates(keep='first',inplace=True) #keep='first'默认值,保留第一次出现的重复记录
#删除缺失值
data.dropna(axis=0,how='any',inplace=True) 
#删除订单行
data.drop(columns=['订单行'],inplace=True,axis=1) 
print(data.info())  # 输出数据框基本信息

#更新索引(drop=True:把原来的索引index列删除,重置index)
data.reset_index(drop=True,inplace=True)

def data_deal(number):  # 定义函数data_deal
    if number.find('万元')!= -1:#找到带有万元的,取出数字,去掉逗号,转成float,*10000
        number_new = float(number[:number.find('万元')].replace(',',''))*10000  # 替换数据中的指定值
        pass  # 占位符,暂不执行任何操作
    else: #找到带有元的,删除元,删除逗号,转成float
        number_new = float(number.replace('元','').replace(',',''))  # 替换数据中的指定值
        pass  # 占位符,暂不执行任何操作
    return number_new  # 返回计算结果
data['销售金额'] = data['销售金额'].map(data_deal)  # 对数据进行映射转换
print(data.describe())  # 输出描述性统计信息

#销售金额为0的情况,删除
data = data[data['销售金额']!=0].copy()
data['销售时间'] = pd.to_datetime(data['销售时间'])  # 转换为日期时间格式
data['交货时间'] = pd.to_datetime(data['交货时间'])  # 转换为日期时间格式
data['销售月份'] = data['销售时间'].dt.month  # 提取日期时间属性
data['交货月份'] = data['交货时间'].dt.month  # 提取日期时间属性

#1.配送是否存在问题研究
#月份维度
data['货品交货状况'] = data['货品交货状况'].str.strip() 
data1 = data.groupby(['销售月份','货品交货状况']).size().unstack() #unstack()把行索引变成列索引
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])  # 提取按时交货列作为data1['按时交货率']变量
print("月份交货状况:\n",data1)  # 输出月份交货状况:\n

data1 = data.groupby(['销售区域','货品交货状况']).size().unstack()  # 按指定列分组聚合
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])  # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False)  # 按指定列排序
print("销售区域交货状况:\n",data1)  # 输出销售区域交货状况:\n
#泰国地区的按时交货率最高,西北地区的按时交货率最低,而且非常明显,可以看出,西北地区的配送服务存在问题,需要重点关注

#货品维度
data1 = data.groupby(['货品','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])  # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False)  # 按指定列排序
print("不同货品交货状况:\n",data1)  # 输出不同货品交货状况:\n
#可以看出货品4的按时交货率最低

#货品和销售区域结合
data1 = data.groupby(['货品','销售区域','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货'])  # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False)  # 按指定列排序
print("货品和销售区域结合的交货状况:\n",data1)  # 输出货品和销售区域结合的交货状况:\n

#2.是否存在尚有潜力的销售区域问题研究
#月份维度
data_month = data.groupby(['销售月份','货品'])['数量'].sum().unstack()
print("月份维度货品的销售情况:\n",data_month)  # 输出月份维度货品的销售情况:\n

# 绘制各个月份的销售情况
data_month.plot(kind='line',figsize=(12,6))
plt.title('各个月份的销售情况')  # 设置图表标题
plt.savefig("1.png")  # 保存图形至文件
#货品2在10月和12月销量猛增,有可能是公司加大了营销力度,也有可能是开发了新的市场

#销售区域维度
data_region = data.groupby(['销售区域','货品'])['数量'].sum().unstack()
print("销售区域货品的销售情况:\n",data_region)  # 输出销售区域货品的销售情况:\n
#从销售区域看,每种货品销售区域为1-3个,货品1有三个销售区域,货品2有两个销售区域,货品3、4、5、6只有一个销售区域,货品2在华东地区还有较大市场空间,适合加大投入,同时货品2在西北配送时效长,用户拒收率高,从成本角度考虑,应该减少投入。

#月份和区域结合
data_month_region = data.groupby(['销售月份','销售区域','货品'])['数量'].sum().unstack()
data_month_region['货品2']  # 查看货品2在各月份和区域的销售数量

#货品2没有开发新的市场,而是在华东地区加大了营销力度 可以在7,8,9月份加大华东地区的营销力度

#3.商品是否存在质量问题研究
data['货品用户反馈'] = data['货品用户反馈'].str.strip()
data3 = data.groupby(['货品','销售区域'])['货品用户反馈'].value_counts().unstack()  # 按指定列分组聚合
data3['拒货率'] = data3['拒货']/data3.sum(axis=1)  # 计算总和
data3['合格率'] = data3['质量合格']/data3.sum(axis=1)  # 计算总和
data3['返修率'] = data3['返修']/data3.sum(axis=1)  # 计算总和
# 按合格率、返修率、拒货率降序排列以识别质量问题货品
data3.sort_values(['合格率','返修率','拒货率'],ascending=False)
#货品3 6 5 的合格率较高,返修率较低,货品1 2 4 的合格率较低,返修率较高,货品1、2、4质量存在问题,建议扩大抽检范围,增大质检力度 货品2在马来西亚的拒货率最高,按时交货率最低,猜测马来西亚对时效性要求较高,需要提高时效性。货品2在马来西亚的销售量较低,可以考虑减少投入。

数据转换:销售金额标准化

原始数据中销售金额的格式不统一,需要转换为数值类型:

原始格式 转换逻辑 转换结果
'5万元' 提取数字 × 10000 50000.0
'12,345元' 删除逗号和’元’ 12345.0
'1,234.5万元' 删除逗号 × 10000 12345000.0

金额转换函数详解

Listing 2
def data_deal(number):
    """处理销售金额,统一转换为元(float类型)"""
    if number.find('万元') != -1:
        # 包含'万元':提取数字部分,去逗号,乘以10000
        number_new = float(
            number[:number.find('万元')].replace(',', '')
        ) * 10000
    else:
        # 包含'元':直接去掉'元'和逗号
        number_new = float(
            number.replace('元', '').replace(',', '')
        )
    return number_new

# 使用 map() 将转换函数应用到整列
data['销售金额'] = data['销售金额'].map(data_deal)

日期处理与特征提取

将字符串类型的日期转换为 datetime,并提取月份特征:

Listing 3
# 字符串 → datetime 类型
data['销售时间'] = pd.to_datetime(data['销售时间'])
data['交货时间'] = pd.to_datetime(data['交货时间'])

# 提取月份特征(1-12),用于时间序列分析
data['销售月份'] = data['销售时间'].dt.month
data['交货月份'] = data['交货时间'].dt.month

# 删除销售金额为0的异常记录
data = data[data['销售金额'] != 0].copy()
  • pd.to_datetime() 将字符串解析为日期对象
  • .dt.month 提取月份数值
  • .copy() 创建副本,避免 SettingWithCopyWarning

配送问题分析:分析思路

配送时效性是物流服务的核心 KPI,分析从三个维度切入:

配送问题分析维度 展示月份、区域、货品三个分析维度 按时交货率 月份维度 区域维度 货品维度 识别季节性波动 定位薄弱区域 锁定问题货品

配送分析:月份维度

按月统计按时交货 vs 晚交货的订单数,计算按时交货率:

Listing 4
# 清洗交货状态字段(去除多余空格)
data['货品交货状况'] = data['货品交货状况'].str.strip()

# 按月份和交货状况分组统计
data1 = data.groupby(
    ['销售月份', '货品交货状况']
).size().unstack()

# 计算按时交货率
data1['按时交货率'] = (
    data1['按时交货'] / (data1['按时交货'] + data1['晚交货'])
)
print('月份交货状况:\n', data1)
  • groupby().size() 统计每个分组的记录数
  • unstack() 将行索引转为列索引,形成交叉表

配送分析:区域维度

按销售区域计算按时交货率,并降序排列以快速识别问题区域:

Listing 5
# 按销售区域和交货状况分组统计
data1 = data.groupby(
    ['销售区域', '货品交货状况']
).size().unstack()

# 计算按时交货率
data1['按时交货率'] = (
    data1['按时交货'] / (data1['按时交货'] + data1['晚交货'])
)

# 按按时交货率降序排列
data1 = data1.sort_values(data1.columns[-1], ascending=False)
print('销售区域交货状况:\n', data1)

关键发现:泰国地区按时交货率最高,西北地区最低,配送服务需重点关注。

配送分析:货品维度

进一步细分到货品层面,识别哪些货品的配送问题最严重:

Listing 6
# 按货品和交货状况分组
data1 = data.groupby(
    ['货品', '货品交货状况']
).size().unstack()

data1['按时交货率'] = (
    data1['按时交货'] / (data1['按时交货'] + data1['晚交货'])
)
data1 = data1.sort_values(data1.columns[-1], ascending=False)
print('不同货品交货状况:\n', data1)

关键发现货品4的按时交货率最低,需要优先改进其物流方案。

配送分析:货品 × 区域交叉分析

将货品和区域两个维度结合,精确定位问题组合:

Listing 7
# 多维度交叉分组
data1 = data.groupby(
    ['货品', '销售区域', '货品交货状况']
).size().unstack()

data1['按时交货率'] = (
    data1['按时交货'] / (data1['按时交货'] + data1['晚交货'])
)
data1 = data1.sort_values(data1.columns[-1], ascending=False)
print('货品和销售区域结合的交货状况:\n', data1)

交叉分析能精确定位「哪个货品在哪个区域」出了问题。

销售潜力分析:月度趋势

从月份维度分析各货品的销售数量变化趋势:

Listing 8
# 按月份和货品分组,统计销售数量
data_month = data.groupby(
    ['销售月份', '货品']
)['数量'].sum().unstack()

print('月份维度货品的销售情况:\n', data_month)
  • ['数量'].sum() 对销售数量求和
  • unstack() 将货品从行索引转为列

销售趋势可视化

使用折线图展示各货品销售数量随月份的变化:

# 绘制折线图
data_month.plot(kind='line', figsize=(12, 6))
plt.title('各个月份的销售情况')
plt.xlabel('月份')
plt.ylabel('销售数量')
plt.grid(True, alpha=0.3)
plt.legend(title='货品')
plt.tight_layout()
plt.show()
Figure 1

关键发现:货品2在10月和12月销量猛增,可能源于营销力度加大。

销售潜力分析:区域维度

分析各货品在不同销售区域的覆盖情况:

Listing 9
# 按销售区域和货品分组统计
data_region = data.groupby(
    ['销售区域', '货品']
)['数量'].sum().unstack()
print('销售区域货品的销售情况:\n', data_region)

关键发现

  • 货品1 覆盖 3 个区域,货品2 覆盖 2 个区域
  • 货品3~6 仅覆盖 1 个区域
  • 货品2在华东地区还有较大市场空间

销售潜力分析:月份 × 区域交叉

结合月份和区域,判断货品2销量增长的来源:

Listing 10
# 三维分组:月份 × 区域 × 货品
data_month_region = data.groupby(
    ['销售月份', '销售区域', '货品']
)['数量'].sum().unstack()

# 查看货品2的详细销售数据
data_month_region['货品2']

结论:货品2并未开发新市场,而是在华东地区加大了营销力度。建议在 7~9 月份继续加大华东地区的投入。

质量问题分析:核心指标

基于用户反馈数据,计算三个质量指标:

指标 计算公式 期望方向
合格率 质量合格数 / 总数 越高越好
返修率 返修数 / 总数 越低越好
拒货率 拒货数 / 总数 越低越好

质量分析代码实现

Listing 11
# 清洗用户反馈字段
data['货品用户反馈'] = data['货品用户反馈'].str.strip()

# 按货品和区域分组,统计各类反馈数量
data3 = data.groupby(
    ['货品', '销售区域']
)['货品用户反馈'].value_counts().unstack()

# 计算三大质量指标
data3['拒货率'] = data3['拒货'] / data3.sum(axis=1)
data3['合格率'] = data3['质量合格'] / data3.sum(axis=1)
data3['返修率'] = data3['返修'] / data3.sum(axis=1)

# 按合格率降序排列
data3 = data3.sort_values(
    ['合格率', '返修率', '拒货率'], ascending=False
)
print(data3)

质量分析关键发现

货品质量对比 展示不同货品的质量表现对比 货品质量表现对比 ✅ 质量较好 • 货品3:合格率高,返修率低 • 货品6:合格率高,返修率低 • 货品5:合格率高,返修率低 建议:保持现有质控标准 ⚠️ 质量需改进 • 货品1:合格率低,返修率高 • 货品2:合格率低,返修率高 • 货品4:合格率低,返修率高 建议:扩大抽检范围,加强质检

综合结论:配送问题

问题发现

  • 西北地区按时交货率显著偏低,配送服务存在系统性问题
  • 货品4在所有货品中按时交货率最低
  • 西北地区 + 货品4 的组合是最需要关注的重点

改进建议

  • 增加西北地区的配送资源和运力
  • 优化货品4的仓储和物流方案
  • 建立按时交货率预警机制

综合结论:销售潜力

问题发现

  • 货品2在 10月、12月 销量猛增(华东地区营销加大)
  • 货品2在华东地区仍有较大市场空间
  • 货品2在西北地区配送时效差、拒收率高

改进建议

  • 7~9 月提前加大华东地区的营销力度
  • 从成本角度,减少货品2在西北地区的投入
  • 拓展货品3~6 的销售区域覆盖

综合结论:质量问题

问题发现

  • 货品1、2、4 的合格率较低,返修率较高
  • 货品2在马来西亚拒货率最高,按时交货率最低
  • 马来西亚市场对时效性要求较高

改进建议

  • 扩大货品1、2、4 的抽检范围,增大质检力度
  • 提升马来西亚地区的配送时效
  • 考虑减少货品2在马来西亚的投入

本章知识点回顾

技术要点 对应方法
数据清洗 drop_duplicates(), dropna(), str.strip()
数据转换 自定义函数 + map()
日期处理 pd.to_datetime(), .dt.month
分组聚合 groupby().size(), groupby().sum()
交叉分析 unstack(), value_counts()
多列排序 sort_values()
可视化 DataFrame.plot(kind='line')